package org.dromara.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.model.LoginUser;
import org.dromara.system.domain.EmailList;
import org.dromara.system.domain.EmailTemplate;
import org.dromara.system.domain.PayOrder;
import org.dromara.system.elastic.entity.PayOrderEs;
import org.dromara.system.kernel.OrderSearchKernel;
import org.dromara.system.kernel.SendEmailKernel;
import org.dromara.system.mapper.EmailListMapper;
import org.dromara.system.mapper.EmailTemplateMapper;
import org.dromara.system.service.IEmailListService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.dromara.system.domain.bo.EmailQueueBo;
import org.dromara.system.domain.vo.EmailQueueVo;
import org.dromara.system.domain.EmailQueue;
import org.dromara.system.mapper.EmailQueueMapper;
import org.dromara.system.service.IEmailQueueService;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 邮件队列Service业务层处理
 *
 * @author Gavino
 * @date 2024-11-18
 */
@RequiredArgsConstructor
@Service
public class EmailQueueServiceImpl implements IEmailQueueService {

    private final EmailQueueMapper baseMapper;
    private final EmailTemplateMapper emailTemplateMapper;
    private final EmailListMapper emailListMapper;
    private final IEmailListService emailListService;
    private final SendEmailKernel sendEmailKernel;
    private final OrderSearchKernel orderSearchKernel;

    /**
     * 查询邮件队列
     *
     * @param queueId 主键
     * @return 邮件队列
     */
    @Override
    public EmailQueueVo queryById(Long queueId){
        return baseMapper.selectVoById(queueId);
    }

    /**
     * 分页查询邮件队列列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 邮件队列分页列表
     */
    @Override
    public TableDataInfo<EmailQueueVo> queryPageList(EmailQueueBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EmailQueue> lqw = buildQueryWrapper(bo);
        lqw.orderByDesc(EmailQueue::getCreateTime);
        Page<EmailQueueVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的邮件队列列表
     *
     * @param bo 查询条件
     * @return 邮件队列列表
     */
    @Override
    public List<EmailQueueVo> queryList(EmailQueueBo bo) {
        LambdaQueryWrapper<EmailQueue> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<EmailQueue> buildQueryWrapper(EmailQueueBo bo) {
        Map<String, Object> params = bo.getParams();

        LambdaQueryWrapper<EmailQueue> lqw = Wrappers.lambdaQuery();
        if(!LoginHelper.isSuperAdmin()) {
            // 非超级管理员查询自己创建的或自己代理的
            Long userId = LoginHelper.getUserId();
            if(LoginHelper.isAgent()) {
                lqw.and(qw -> qw.eq(EmailQueue::getCreateId, userId).or().eq(EmailQueue::getAgentId, userId));
            } else {
                lqw.eq(EmailQueue::getCreateId, userId);
            }
            // 未删除的
            bo.setIsDelete(0);
        }

        lqw.eq(bo.getType() != null, EmailQueue::getType, bo.getType());
        lqw.eq(bo.getTemplateId() != null, EmailQueue::getTemplateId, bo.getTemplateId());
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), EmailQueue::getTitle, bo.getTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getTheme()), EmailQueue::getTheme, bo.getTheme());
        lqw.eq(StringUtils.isNotBlank(bo.getTemplate()), EmailQueue::getTemplate, bo.getTemplate());
        lqw.eq(StringUtils.isNotBlank(bo.getSendEmailId()), EmailQueue::getSendEmailId, bo.getSendEmailId());
        lqw.eq(StringUtils.isNotBlank(bo.getSendEmailAct()), EmailQueue::getSendEmailAct, bo.getSendEmailAct());
        lqw.eq(bo.getDelayTime() != null, EmailQueue::getDelayTime, bo.getDelayTime());
        lqw.eq(bo.getDelaySendNum() != null, EmailQueue::getDelaySendNum, bo.getDelaySendNum());
        lqw.eq(bo.getStatus() != null, EmailQueue::getStatus, bo.getStatus());
        lqw.eq(bo.getErrTime() != null, EmailQueue::getErrTime, bo.getErrTime());
        lqw.eq(StringUtils.isNotBlank(bo.getErrContent()), EmailQueue::getErrContent, bo.getErrContent());
        lqw.eq(bo.getCompleteTime() != null, EmailQueue::getCompleteTime, bo.getCompleteTime());
        lqw.eq(bo.getIsDelete() != null, EmailQueue::getIsDelete, bo.getIsDelete());
        lqw.eq(bo.getCreateId() != null, EmailQueue::getCreateId, bo.getCreateId());
        lqw.like(StringUtils.isNotBlank(bo.getCreateName()), EmailQueue::getCreateName, bo.getCreateName());
        lqw.eq(bo.getUpdateId() != null, EmailQueue::getUpdateId, bo.getUpdateId());
        lqw.like(StringUtils.isNotBlank(bo.getUpdateName()), EmailQueue::getUpdateName, bo.getUpdateName());
        return lqw;
    }

    /**
     * 新增邮件队列
     *
     * @param bo 邮件队列
     * @return 是否新增成功
     */
    @Transactional
    @Override
    public Boolean insertByBo(EmailQueueBo bo) {
        EmailQueue add = MapstructUtils.convert(bo, EmailQueue.class);
        add.setIsDelete(0);

        add.setCreateId(LoginHelper.getUserId());
        add.setCreateName(LoginHelper.getUsername());
        add.setAgentId(LoginHelper.getLoginUser().getAgentId());
        add.setAgentName(LoginHelper.getLoginUser().getAgentName());
        add.setCreateTime(DateUtils.getNowDate());

        EmailTemplate template = emailTemplateMapper.selectById(add.getTemplateId());
        add.setTheme(template.getTheme());

        add.setIsDelete(0);

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            // 插入邮件列表
            insertEmailList(add, bo.getEmailList());
            bo.setQueueId(add.getQueueId());
        }
        return flag;
    }

    /**
     * 新增邮件列表信息
     *
     * @param emailQueue 邮件队列对象
     */
    public void insertEmailList(EmailQueue emailQueue, List<EmailList> emails) {
        // 获取当前的用户信息
        LoginUser loginUser = LoginHelper.getLoginUser();

        Map<String, PayOrder> orderMap = new HashMap<>();
        if (emailQueue.getType() == 1) {
            List<String> orderNos = emails.stream().map(EmailList::getOrderNo).collect(Collectors.toList());

            //查询订单信息
            BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
            queryBuilder.filter(new TermsQueryBuilder("orderNo.keyword", orderNos));
            PageImpl<PayOrder> page = orderSearchKernel.queryOrderEsPage(queryBuilder, null, null, PayOrder.class, null, Arrays.stream(PayOrder.class.getDeclaredFields()).map(Field::getName).toArray(String[]::new));
            List<PayOrder> tmpList = page.getContent();
            //订单信息转换为map
            orderMap = tmpList.stream().collect(Collectors.toMap(PayOrder::getOrderNo, Function.identity()));
        }

        Long queueId = emailQueue.getQueueId();
        if (emails != null && !emails.isEmpty()) {
            List<EmailList> list = new ArrayList<>();
            for (EmailList email : emails) {
                if (StringUtils.isNotEmpty(email.getOrderNo())) {
                    PayOrder order = orderMap.get(email.getOrderNo());
                    if (order == null) {
                        throw new ServiceException("订单号" + email.getOrderNo() + "无效");
                    }
                    email.setOrderId(order.getOrderId());
                    email.setReceiveEmail(order.getCustomerEmail());
                }
                email.setTemplateId(emailQueue.getTemplateId());
                email.setType(2);
                email.setQueueId(queueId);
                email.setIsDelete(0);
                email.setStatus(emailQueue.getStatus());
                email.setCreateId(emailQueue.getCreateId());
                email.setCreateName(emailQueue.getCreateName());
                email.setAgentId(emailQueue.getAgentId());
                email.setAgentName(emailQueue.getAgentName());
                email.setCreateTime(emailQueue.getCreateTime());
                list.add(email);
            }

            emailListMapper.insertBatch(list);

            //异步发送邮件
            if (emailQueue.getStatus() == 2) {
                sendEmailKernel.asyncSendEmail(emailQueue, emails);
            }
        }
    }

    /**
     * 发送邮件队列
     *
     * @param queueId 邮件队列
     * @return 邮件队列集合
     */
    @Override
    public R<?> sendEmailQueue(Long queueId, Integer status, LoginUser loginUser) {
        if(loginUser == null) {
            return R.fail("未查询到用户信息");
        }

        EmailQueue queue = baseMapper.selectById(queueId);
        if (queue == null) {
            return R.fail("未查询到队列信息");
        }

        // 非超级管理员查询自己创建的或自己代理的
        Long userId = LoginHelper.getUserId();
        if(LoginHelper.isAgent()) {
            if (!Objects.equals(queue.getCreateId(), userId) && !Objects.equals(queue.getAgentId(), userId)) {
                return R.fail("没有操作权限");
            }
        } else if (!LoginHelper.isSuperAdmin() && !Objects.equals(queue.getCreateId(), userId)) {
            return R.fail("没有操作权限");
        }

        if (queue.getStatus() == 2) {
            return R.fail("该队列当前状态不能发送");
        }

        //更新需要发送的邮件的状态
        emailListService.updateEmailStatusByQueueId(queue.getQueueId(), status, 2);

        //更新状态
        EmailQueue upQueue = new EmailQueue();
        upQueue.setQueueId(queue.getQueueId());
        upQueue.setStatus(2);
        upQueue.setUpdateTime(DateUtils.getNowDate());
        baseMapper.updateById(upQueue);

        return sendEmailQueueMQ(queue.getQueueId());
    }

    /**
     * 所有失败邮件队列重发
     *
     * @return 邮件队列集合
     */
    @Override
    public R<?> reSendAll() {
        // 获取当前的用户信息
        LoginUser loginUser = LoginHelper.getLoginUser();
        if(loginUser == null) {
            return R.fail("未查询到用户信息");
        }

        LambdaQueryWrapper<EmailList> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmailList::getStatus, 4);//失败的
        queryWrapper.eq(EmailList::getType, 2);//物流邮件
        queryWrapper.isNotNull(EmailList::getQueueId);//队列id不为空

        Long userId = LoginHelper.getUserId();
        if (LoginHelper.isAgent()) {
            queryWrapper.and(qw -> qw.eq(EmailList::getCreateId, userId).or().eq(EmailList::getAgentId, userId));
        }
        else if (!LoginHelper.isSuperAdmin()) {
            queryWrapper.eq(EmailList::getCreateId, userId);
        }

        queryWrapper.select(EmailList::getQueueId).groupBy(EmailList::getQueueId);
        List<EmailList> emails = emailListMapper.selectList(queryWrapper);

        Set<Long> queueIds = emails.stream().map(EmailList::getQueueId).collect(Collectors.toSet());
        if(queueIds.isEmpty()) {
            return R.fail("没有可重发的邮件");
        }

        //异步发送邮件
        CompletableFuture.runAsync(() -> {
            for (Long queueId : queueIds) {
                sendEmailQueue(queueId, 4, loginUser);
            }
        });

        return R.ok("发送中");
    }

    /**
     * 发送邮件队列
     *
     * @param queueId 邮件队列
     * @return 邮件队列集合
     */
    @Override
    public R<?> sendEmailQueueMQ(Long queueId) {

        EmailQueue queue = baseMapper.selectById(queueId);
        if (queue == null || queue.getIsDelete() == 1) {
            return R.fail("未查询到队列信息");
        }

        if (queue.getStatus() != 2) {
            return R.fail("该队列当前状态不能发送");
        }

        //查询发送中的邮件
        LambdaQueryWrapper<EmailList> query = new LambdaQueryWrapper<>();
        query.eq(EmailList::getQueueId, queue.getQueueId()).eq(EmailList::getStatus, 2);
        List<EmailList> emList = emailListMapper.selectList(query);
        if (emList.isEmpty()) {
            //更新状态
            LambdaUpdateWrapper<EmailQueue> update = new LambdaUpdateWrapper<EmailQueue>().eq(EmailQueue::getQueueId, queue.getQueueId());
            update.set(EmailQueue::getStatus, 3);
            update.set(EmailQueue::getErrTime, null);
            update.set(EmailQueue::getErrContent, "");
            update.set(EmailQueue::getUpdateTime, DateUtils.getNowDate());
            update.set(EmailQueue::getCompleteTime, DateUtils.getNowDate());
            baseMapper.update(update);
            return R.fail("没有可发送的邮件");
        }

        //异步发送邮件
        sendEmailKernel.asyncSendEmail(queue, emList);

        return R.ok("发送中");
    }

    /**
     * 修改邮件队列
     *
     * @param bo 邮件队列
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(EmailQueueBo bo) {
        EmailQueue update = MapstructUtils.convert(bo, EmailQueue.class);
        update.setUpdateId(LoginHelper.getUserId());
        update.setUpdateName(LoginHelper.getUsername());
        update.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 校验并批量删除邮件队列信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        LambdaQueryWrapper<EmailQueue> query = new LambdaQueryWrapper<>();
        query.in(EmailQueue::getQueueId, ids);
        if (LoginHelper.isAgent()) {
            // 代理查询自己创建的或自己代理的
            Long userId = LoginHelper.getUserId();
            query.and(qw -> qw.eq(EmailQueue::getCreateId, userId).or().eq(EmailQueue::getAgentId, userId));
        }
        else if (!LoginHelper.isSuperAdmin()) {
            // 非超级管理员查询自己创建的
            query.eq(EmailQueue::getCreateId, LoginHelper.getUserId());
        }

        boolean tag = baseMapper.delete(query) > 0;
        if(tag) {
            //删除邮件列表
            emailListMapper.delete(new LambdaQueryWrapper<EmailList>().eq(EmailList::getQueueId, ids));
        }
        return tag;
    }
}
